﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;

namespace Narwhunderful.Aphelia.Framework
{

    public class UpdatableComponent : DesignableComponent, IUpdatableComponent
    {

        public UpdatableComponent(Game game)
            : base()
        {
            _game = game;
        }

        #region IDesignableComponent

        protected internal override void OnDesigningChanged()
        {
            if (!base.IsDesigning) _needsUpdate = true;
            base.OnDesigningChanged();
        }

        #endregion

        #region IUpdatableComponent

        public event EventHandler<EventArgs> UpdateOrderChanged = null;
        public event EventHandler<EventArgs> EnabledChanged = null;

        Game _game;
        public virtual Game Game
        {
            get
            {
                return _game;
            }
        }

        bool _alwaysNeedsUpdate = false;
        public virtual bool AlwaysNeedsUpdate
        {
            get
            {
                return _alwaysNeedsUpdate;
            }
            set
            {
                _alwaysNeedsUpdate = value;
            }
        }

        bool _needsUpdate = true;
        public virtual bool NeedsUpdate
        {
            get
            {
                return _needsUpdate;
            }
            set
            {
                _needsUpdate = value;
            }
        }

        bool _isEnabled = true;
        public virtual bool IsEnabled
        {
            get
            {
                return _isEnabled;
            }
            set
            {
                if (_isEnabled != value)
                {
                    _isEnabled = value;
                    OnEnabledChanged();
                }
            }
        }

        bool _isUpdating = false;
        public bool IsUpdating
        {
            get
            {
                return _isUpdating;
            }
            protected internal set
            {
                _isUpdating = value;
            }
        }

        int _updateOrder = 0;
        public virtual int UpdateOrder
        {
            get
            {
                return _updateOrder;
            }
            set
            {
                if (_updateOrder != value)
                {
                    _updateOrder = value;
                    OnUpdateOrderChanged();
                }
            }
        }

        public virtual void Update(GameTime gameTime)
        {
            if (CanUpdate(gameTime))
            {
                BeginUpdate();
                InternalUpdate(gameTime);
                EndUpdate();
            }
        }

        public virtual bool CanUpdate(GameTime gameTime)
        {
            if (!_alwaysNeedsUpdate)
            {
                if (!_needsUpdate) return false;
            }
            if (_isUpdating) return false;
            if (!_isEnabled) return false;
            return !base.IsDesigning;
        }

        protected virtual void BeginUpdate()
        {
            _isUpdating = true;
            _needsUpdate = false;
        }

        protected virtual void InternalUpdate(GameTime gameTime)
        {
        }

        protected virtual void EndUpdate()
        {
            _isUpdating = false;
        }

        protected virtual void OnUpdateOrderChanged()
        {
            UpdateOrderChanged.SafeInvoke(this, new EventArgs());
        }

        protected virtual void OnEnabledChanged()
        {
            EnabledChanged.SafeInvoke(this, new EventArgs());
        }

        #endregion
       
    }

}
